﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using myOSity.API;

namespace solitaire
{
    public partial class moSol : UserControl
    {
        private Stack<Card> _deck = new Stack<Card>();              //Represents a deck of cards
        private Random _r = new Random();                           //Randome number generator
        private bool _mouseCaptured = false;                        //flags whether something is being dragged or not
        private Point _offSet;                                      //Offsets _draggableColumn position while dragging it with the mouse
        private DiscardPile _discardPile;                           //Represents face-up cards that have been turn over from the _startPile
        private StartPile _startPile;                               //Represents face-down cards that are not yet in play
        private FinishPile[] _finishPiles = new FinishPile[4];      //Contains objects representing where finished cards go
        private CardColumn[] _cardColumns = new CardColumn[7];      //Contains objects representing each column of cards in the playfield
        private CardColumn _draggableColumn = new CardColumn();     //Used as a container to drag cards around the playfield
        private PreferencesDialog _prefDialog = new PreferencesDialog();
        private System.Windows.Threading.DispatcherTimer _timer;
        private bool _firstLoad = true;

        #region Initialization and UI Methods
        //Class Constructor
        public moSol()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Page_Loaded);
            Canvas.SetZIndex(_draggableColumn, 999); //set the draggable column to the highest z-index

        }

        /// <summary>
        /// Fires after this UserControl has completely loaded into the Silverlight rendered display
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Page_Loaded(object sender, RoutedEventArgs e)
        {
            if (_firstLoad)
            {
                _firstLoad = false;
                #region Reset Elements
                GameStatus.GameOver = false;
                GameStatus.Passes = 0;
                GameStatus.BankRoll = 0;
                GameStatus.ElapsedSeconds = new TimeSpan();

                _timer = new System.Windows.Threading.DispatcherTimer();
                _timer.Interval = new TimeSpan(0, 0, 1);
                _timer.Tick += new EventHandler(_timer_Tick);

                _discardPile = new DiscardPile();

                _startPile = new StartPile();
                _startPile.StartCardClicked += new EventHandler<CardReturnEventArgs>(_startPile_StartCardClicked);
                _startPile.ellipse1.Visibility = Visibility.Visible;
                _startPile.cvX.Visibility = Visibility.Collapsed;

                _finishPiles[0] = new FinishPile();
                _finishPiles[1] = new FinishPile();
                _finishPiles[2] = new FinishPile();
                _finishPiles[3] = new FinishPile();

                Canvas.SetZIndex(_discardPile, 0);
                Canvas.SetZIndex(_startPile, 0);
                Canvas.SetZIndex(_finishPiles[0], 0);
                Canvas.SetZIndex(_finishPiles[1], 0);
                Canvas.SetZIndex(_finishPiles[2], 0);
                Canvas.SetZIndex(_finishPiles[3], 0);

                //set positions
                Canvas.SetLeft(_startPile, 20);
                Canvas.SetTop(_startPile, 30);
                Canvas.SetLeft(_discardPile, 120);
                Canvas.SetTop(_discardPile, 30);
                Canvas.SetLeft(_finishPiles[0], 320);
                Canvas.SetTop(_finishPiles[0], 30);
                Canvas.SetLeft(_finishPiles[1], 420);
                Canvas.SetTop(_finishPiles[1], 30);
                Canvas.SetLeft(_finishPiles[2], 520);
                Canvas.SetTop(_finishPiles[2], 30);
                Canvas.SetLeft(_finishPiles[3], 620);
                Canvas.SetTop(_finishPiles[3], 30);

                //CardColumns
                for (int i = 0; i < 7; i++)
                {
                    _cardColumns[i] = new CardColumn();
                    Canvas.SetZIndex(_cardColumns[i], 0);
                    Canvas.SetTop(_cardColumns[i], 175);
                    Canvas.SetLeft(_cardColumns[i], (i * 100) + 20);
                    this.LayoutRoot.Children.Add(_cardColumns[i]);
                }

                this.LayoutRoot.Children.Add(_startPile);
                this.LayoutRoot.Children.Add(_discardPile);
                this.LayoutRoot.Children.Add(_finishPiles[0]);
                this.LayoutRoot.Children.Add(_finishPiles[1]);
                this.LayoutRoot.Children.Add(_finishPiles[2]);
                this.LayoutRoot.Children.Add(_finishPiles[3]);
                #endregion

                DealCards();

                InitPrefs();
                btnResetBalance.Visibility = tbBalance.Visibility = (GameStatus.Preferences.EnableVegasRules) ? Visibility.Visible : Visibility.Collapsed;
                tbTimer.Visibility = (GameStatus.Preferences.EnableTimer) ? Visibility.Visible : Visibility.Collapsed;

                this.LayoutRoot.MouseMove += new MouseEventHandler(LayoutRoot_MouseMove);
                _startPile.LayoutRoot.MouseLeftButtonDown += new MouseButtonEventHandler(LayoutRoot_MouseLeftButtonDown);
            }
        }

        void _timer_Tick(object sender, EventArgs e)
        {
            GameStatus.ElapsedSeconds += TimeSpan.FromSeconds(1);
            UpdateTimeDisplay();
        }
        /// <summary>
        /// Resets the board and starts a new game
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnNewGame_Click(object sender, RoutedEventArgs e)
        {
            StartNewGame();
        }
        private void StartNewGame()
        {
            for (int i = 0; i < 7; i++)
            {
                _cardColumns[i].Clear();
            }

            _startPile.ellipse1.Visibility = Visibility.Visible;
            _startPile.cvX.Visibility = Visibility.Collapsed;

            GameStatus.GameOver = false;
            GameStatus.Passes = 0;

            btnResetBalance.Visibility = tbBalance.Visibility = (GameStatus.Preferences.EnableVegasRules) ? Visibility.Visible : Visibility.Collapsed;
            tbTimer.Visibility = (GameStatus.Preferences.EnableTimer) ? Visibility.Visible : Visibility.Collapsed;

            _finishPiles[0].Clear();
            _finishPiles[1].Clear();
            _finishPiles[2].Clear();
            _finishPiles[3].Clear();
            _startPile.Clear();
            _discardPile.Clear();

            if (GameStatus.Preferences.EnableVegasRules)
            {
                GameStatus.BankRoll -= 50;
                UpdateBankRollDisplay();
            }
            if (GameStatus.Preferences.EnableTimer)
            {
                GameStatus.ElapsedSeconds = TimeSpan.FromSeconds(0);
                UpdateTimeDisplay();
                _timer.Start();
            }

            DealCards();
        }
        /// <summary>
        /// Initializes default preferences
        /// TODO: allow user to change/save/load preferences
        /// </summary>
        private void InitPrefs()
        {
            GameStatus.Preferences = new GameSettings();
            GameStatus.Preferences.DrawMode = DrawModes.DrawThree;
            GameStatus.Preferences.EnableScoring = false;
            GameStatus.Preferences.EnableTimer = false;
            GameStatus.Preferences.EnableVegasRules = false;
        }

        #endregion

        #region Event Handlers for the Options Dialog
        private void btnPrefs_Click(object sender, RoutedEventArgs e)
        {
            ModalCoverEnabled = true;
            CenterInLayout(_prefDialog);
            _prefDialog.btnCancelPrefs.Click += new RoutedEventHandler(btnCancelPrefs_Click);
            _prefDialog.btnSubmitPrefs.Click += new RoutedEventHandler(btnSubmitPrefs_Click);
            if (GameStatus.Preferences.DrawMode == DrawModes.DrawOne)
                _prefDialog.rbDrawOne.IsChecked = true;
            else
                _prefDialog.rbDrawThree.IsChecked = true;

            _prefDialog.cbTimedGame.IsChecked = GameStatus.Preferences.EnableTimer;
            _prefDialog.cbEnableVegas.IsChecked = GameStatus.Preferences.EnableVegasRules;
            LayoutRoot.Children.Add(_prefDialog);
        }
        void btnSubmitPrefs_Click(object sender, RoutedEventArgs e)
        {
            bool _changeFlag = false;
            DrawModes cdm = GameStatus.Preferences.DrawMode;

            if ((bool)_prefDialog.rbDrawOne.IsChecked)
                GameStatus.Preferences.DrawMode = DrawModes.DrawOne;
            else
                GameStatus.Preferences.DrawMode = DrawModes.DrawThree;

            if (cdm != GameStatus.Preferences.DrawMode) _changeFlag = true;

            if (GameStatus.Preferences.EnableVegasRules != _prefDialog.cbEnableVegas.IsChecked)
            {
                GameStatus.Preferences.EnableVegasRules = (bool)_prefDialog.cbEnableVegas.IsChecked;
                if ((bool)_prefDialog.cbEnableVegas.IsChecked) GameStatus.BankRoll = 0;
                _changeFlag = true;
            }
            if (GameStatus.Preferences.EnableTimer != _prefDialog.cbTimedGame.IsChecked)
            {
                GameStatus.Preferences.EnableTimer = (bool)_prefDialog.cbTimedGame.IsChecked;
                if ((bool)_prefDialog.cbTimedGame.IsChecked)
                    _timer.Start();
                else
                    _timer.Stop();
                _changeFlag = true;
            }

            LayoutRoot.Children.Remove(_prefDialog);
            ModalCoverEnabled = false;

            if (_changeFlag) StartNewGame();
        }
        void btnCancelPrefs_Click(object sender, RoutedEventArgs e)
        {
            LayoutRoot.Children.Remove(_prefDialog);
            ModalCoverEnabled = false;
        }
        #endregion

        #region Click, Drag, And Drop Handlers
        void Card_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!GameStatus.GameOver)
            {
                Card c = (Card)sender;
                if (((IDraggable)c).DragEnabled)
                {
                    this.AddCardsToDraggableColumn(c.FromContainer.RetrieveCardAndDescendants(c));
                    _offSet = new Point(38, 20);
                    Canvas.SetLeft(_draggableColumn, e.GetPosition(LayoutRoot).X - _offSet.X);
                    Canvas.SetTop(_draggableColumn, e.GetPosition(LayoutRoot).Y - _offSet.Y);
                    _mouseCaptured = true;
                    this.LayoutRoot.MouseLeftButtonUp += new MouseButtonEventHandler(Handler_MouseLeftButtonUp);
                    _draggableColumn.MouseLeftButtonUp += new MouseButtonEventHandler(Handler_MouseLeftButtonUp);
                }
                e.Handled = true;
            }
        }
        /// <summary>
        /// Determines what action to take after the users has completed a drag operation
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Handler_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            _mouseCaptured = false;
            //remove the mouseup events from the elements, we don't need them until the next drag
            try
            {
                _draggableColumn.MouseLeftButtonUp -= new MouseButtonEventHandler(Handler_MouseLeftButtonUp);
                this.LayoutRoot.MouseLeftButtonUp -= new MouseButtonEventHandler(Handler_MouseLeftButtonUp);
            }
            catch { }

            //Check card columns to see if the card landed inside
            foreach (ICardContainer cc in _cardColumns)
            {
                if (cc.IsInside(e.GetPosition(LayoutRoot)))
                {
                    //if the column reports that the card(s) can validly be placed in this column
                    if (((CardColumn)cc).IsGoodCardCandidate(_draggableColumn.BottomCard))
                    {
                        PlaceCards(cc); //Put the cards into the column
                        e.Handled = true;
                        return;
                    }
                }
            }

            //If the player is dragging a single card, see if it landed in one of the finish piles
            if (_draggableColumn.TotalCards == 1)
            {
                foreach (ICardContainer cc in _finishPiles)
                {
                    if (cc.IsInside(e.GetPosition(LayoutRoot)))
                    {
                        //if the finished pile reports that the card can validly be placed there
                        if (((FinishPile)cc).IsGoodCardCandidate(_draggableColumn.BottomCard))
                        {
                            PlaceCards(cc);  //Put the card into the pile
                            e.Handled = true;
                            return;
                        }
                    }
                }
            }

            //If the card(s) where not dropped into a valid location, set the card(s) back to the previous location...
            Card c = _draggableColumn.BottomCard;
            PlaceCards(c.FromContainer);
            e.Handled = true;
        }
        /// <summary>
        /// Repositions the draggable column around the playfield as the user drags it
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void LayoutRoot_MouseMove(object sender, MouseEventArgs e)
        {
            if (_mouseCaptured)
            {
                Point _mousePos = e.GetPosition(LayoutRoot);
                Canvas.SetLeft(_draggableColumn, _mousePos.X - _offSet.X);
                Canvas.SetTop(_draggableColumn, _mousePos.Y - _offSet.Y);
            }
        }
        /// <summary>
        /// When the start pile is empty and the user clicks on it, takes the cards from the discard pile and puts them back into the start pile
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void LayoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!GameStatus.GameOver && _startPile.TotalCards == 0)
            {
                //When Vegas Rules are enabled, control the number of passes allowed back to the start pile
                // DrawModes.DrawOne = 1 Pass only
                // DrawModes.DrawThree = 3 Passes only
                if (GameStatus.Preferences.EnableVegasRules)
                {
                    if ((GameStatus.Preferences.DrawMode == DrawModes.DrawOne && GameStatus.Passes == 0) || (GameStatus.Preferences.DrawMode == DrawModes.DrawThree && GameStatus.Passes == 2))
                    {
                        return;
                    }
                    else
                    {
                        GameStatus.Passes++;
                    }
                }
                while (_discardPile.TotalCards > 0)
                {
                    _startPile.AddCard(_discardPile.RetrieveTopCard());
                }
            }
        }
        /// <summary>
        /// Takes a card from the start pile and places it face up on the discard pile
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _startPile_StartCardClicked(object sender, CardReturnEventArgs e)
        {
            if (!GameStatus.GameOver)
            {
                if (GameStatus.Preferences.DrawMode == DrawModes.DrawOne)
                {
                    _discardPile.AddCard(e.CardReturned);
                    e.CardReturned.MouseLeftButtonDown += new MouseButtonEventHandler(Card_MouseLeftButtonDown);
                    e.CardReturned.DragEnabled = true;
                }
                else if (GameStatus.Preferences.DrawMode == DrawModes.DrawThree)
                {
                    _discardPile.AddCard(e.CardReturned);
                    e.CardReturned.MouseLeftButtonDown += new MouseButtonEventHandler(Card_MouseLeftButtonDown);

                    if (_startPile.TotalCards > 0)
                    {
                        Card tc1 = _startPile.RetrieveTopCard();
                        _discardPile.AddCard(tc1);
                        tc1.MouseLeftButtonDown += new MouseButtonEventHandler(Card_MouseLeftButtonDown);
                    }

                    if (_startPile.TotalCards > 0)
                    {
                        Card tc = _startPile.RetrieveTopCard();
                        _discardPile.AddCard(tc);
                        tc.MouseLeftButtonDown += new MouseButtonEventHandler(Card_MouseLeftButtonDown);
                    }
                }

                //Adjust the look of the start pile background, depending on whether or not the user can make a pass
                if (_startPile.TotalCards == 0)
                {
                    if (GameStatus.Preferences.EnableVegasRules && (GameStatus.Preferences.DrawMode == DrawModes.DrawOne && GameStatus.Passes == 0) || (GameStatus.Preferences.DrawMode == DrawModes.DrawThree && GameStatus.Passes == 2))
                    {
                        _startPile.ellipse1.Visibility = Visibility.Collapsed;
                        _startPile.cvX.Visibility = Visibility.Visible;
                    }
                    else
                    {
                        _startPile.ellipse1.Visibility = Visibility.Visible;
                        _startPile.cvX.Visibility = Visibility.Collapsed;
                    }
                }
            }
        }
        /// <summary>
        /// Takes an array of cards, and puts them into the draggable column so the user can move them around the playfield
        /// </summary>
        /// <param name="c"></param>
        public void AddCardsToDraggableColumn(Card[] c)
        {
            foreach (Card cc in c)
            {
                _draggableColumn.AddCardNoContainerUpdate(cc);
            }
            this.LayoutRoot.Children.Add(_draggableColumn);
        }
        /// <summary>
        /// Takes cards from the draggablecolumn and places them into the appropriate ICardContainer
        /// </summary>
        /// <param name="c"></param>
        public void PlaceCards(ICardContainer c)
        {
            this.LayoutRoot.Children.Remove(_draggableColumn);
            while (_draggableColumn.BottomCard != null)
            {
                Card ncc = _draggableColumn.RetrieveCard(_draggableColumn.BottomCard);
                ncc.MouseLeftButtonDown += new MouseButtonEventHandler(Card_MouseLeftButtonDown);
                c.AddCard(ncc);
            }
            AfterTurn();
        }
        #endregion

        #region Helper Methods
        /// <summary>
        /// Updates the game with any changes that need to be made after the player has taken some action.
        /// </summary>
        private void AfterTurn()
        {
            foreach (CardColumn cc in _cardColumns)
            {
                cc.FlipBottomCardUp();
            }

            UpdateBankRollDisplay();
            DetermineGameOver();
        }

        private void DetermineGameOver()
        {
            int x = (from cc in _finishPiles
                     where cc.PeekTopCard() != null && cc.PeekTopCard().CardValue == CardValue.King
                     select cc).Count();

            if (x == 4)
            {
                GameStatus.GameOver = true;
                MessageBox.Show("Congratulations!  You win!", "Game Over", MessageBoxButton.OK);
            }
        }

        /// <summary>
        /// Returns a randomized deck of cards
        /// </summary>
        /// <returns></returns>
        private Stack<Card> GetShuffledDeck()
        {
            Stack<Card> newDeck = new Stack<Card>();
            List<Card> _orderedDeck = GetOrderedDeck();

            while (_orderedDeck.Count > 0)
            {
                int c = _r.Next(0, _orderedDeck.Count);
                newDeck.Push(_orderedDeck[c].Clone());
                _orderedDeck.RemoveAt(c);
            }

            return newDeck;
        }
        /// <summary>
        /// Initializes an ordered deck of cards
        /// </summary>
        /// <returns></returns>
        private static List<Card> GetOrderedDeck()
        {
            List<Card> _orderedDeck = new List<Card>(52);
            _orderedDeck.Add(new Card(CardValue.Ace, CardSuit.Hearts));
            _orderedDeck.Add(new Card(CardValue.Two, CardSuit.Hearts));
            _orderedDeck.Add(new Card(CardValue.Three, CardSuit.Hearts));
            _orderedDeck.Add(new Card(CardValue.Four, CardSuit.Hearts));
            _orderedDeck.Add(new Card(CardValue.Five, CardSuit.Hearts));
            _orderedDeck.Add(new Card(CardValue.Six, CardSuit.Hearts));
            _orderedDeck.Add(new Card(CardValue.Seven, CardSuit.Hearts));
            _orderedDeck.Add(new Card(CardValue.Eight, CardSuit.Hearts));
            _orderedDeck.Add(new Card(CardValue.Nine, CardSuit.Hearts));
            _orderedDeck.Add(new Card(CardValue.Ten, CardSuit.Hearts));
            _orderedDeck.Add(new Card(CardValue.Jack, CardSuit.Hearts));
            _orderedDeck.Add(new Card(CardValue.Queen, CardSuit.Hearts));
            _orderedDeck.Add(new Card(CardValue.King, CardSuit.Hearts));

            _orderedDeck.Add(new Card(CardValue.Ace, CardSuit.Diamonds));
            _orderedDeck.Add(new Card(CardValue.Two, CardSuit.Diamonds));
            _orderedDeck.Add(new Card(CardValue.Three, CardSuit.Diamonds));
            _orderedDeck.Add(new Card(CardValue.Four, CardSuit.Diamonds));
            _orderedDeck.Add(new Card(CardValue.Five, CardSuit.Diamonds));
            _orderedDeck.Add(new Card(CardValue.Six, CardSuit.Diamonds));
            _orderedDeck.Add(new Card(CardValue.Seven, CardSuit.Diamonds));
            _orderedDeck.Add(new Card(CardValue.Eight, CardSuit.Diamonds));
            _orderedDeck.Add(new Card(CardValue.Nine, CardSuit.Diamonds));
            _orderedDeck.Add(new Card(CardValue.Ten, CardSuit.Diamonds));
            _orderedDeck.Add(new Card(CardValue.Jack, CardSuit.Diamonds));
            _orderedDeck.Add(new Card(CardValue.Queen, CardSuit.Diamonds));
            _orderedDeck.Add(new Card(CardValue.King, CardSuit.Diamonds));

            _orderedDeck.Add(new Card(CardValue.Ace, CardSuit.Spades));
            _orderedDeck.Add(new Card(CardValue.Two, CardSuit.Spades));
            _orderedDeck.Add(new Card(CardValue.Three, CardSuit.Spades));
            _orderedDeck.Add(new Card(CardValue.Four, CardSuit.Spades));
            _orderedDeck.Add(new Card(CardValue.Five, CardSuit.Spades));
            _orderedDeck.Add(new Card(CardValue.Six, CardSuit.Spades));
            _orderedDeck.Add(new Card(CardValue.Seven, CardSuit.Spades));
            _orderedDeck.Add(new Card(CardValue.Eight, CardSuit.Spades));
            _orderedDeck.Add(new Card(CardValue.Nine, CardSuit.Spades));
            _orderedDeck.Add(new Card(CardValue.Ten, CardSuit.Spades));
            _orderedDeck.Add(new Card(CardValue.Jack, CardSuit.Spades));
            _orderedDeck.Add(new Card(CardValue.Queen, CardSuit.Spades));
            _orderedDeck.Add(new Card(CardValue.King, CardSuit.Spades));

            _orderedDeck.Add(new Card(CardValue.Ace, CardSuit.Clubs));
            _orderedDeck.Add(new Card(CardValue.Two, CardSuit.Clubs));
            _orderedDeck.Add(new Card(CardValue.Three, CardSuit.Clubs));
            _orderedDeck.Add(new Card(CardValue.Four, CardSuit.Clubs));
            _orderedDeck.Add(new Card(CardValue.Five, CardSuit.Clubs));
            _orderedDeck.Add(new Card(CardValue.Six, CardSuit.Clubs));
            _orderedDeck.Add(new Card(CardValue.Seven, CardSuit.Clubs));
            _orderedDeck.Add(new Card(CardValue.Eight, CardSuit.Clubs));
            _orderedDeck.Add(new Card(CardValue.Nine, CardSuit.Clubs));
            _orderedDeck.Add(new Card(CardValue.Ten, CardSuit.Clubs));
            _orderedDeck.Add(new Card(CardValue.Jack, CardSuit.Clubs));
            _orderedDeck.Add(new Card(CardValue.Queen, CardSuit.Clubs));
            _orderedDeck.Add(new Card(CardValue.King, CardSuit.Clubs));

            return _orderedDeck;
        }
        /// <summary>
        /// Distributes the cards around the playfield
        /// </summary>
        private void DealCards()
        {
            _deck = GetShuffledDeck();  //get a new set of shuffled cards

            //Deal cards to the field
            for (int i = 0; i < 7; i++)
            {
                for (int ii = 0; ii <= i; ii++)
                {
                    Card c = _deck.Pop();
                    c.DragEnabled = true;
                    //Register for a mouse click on the card...
                    c.DraggableElement.MouseLeftButtonDown += new MouseButtonEventHandler(Card_MouseLeftButtonDown);
                    c.FaceUp = (ii < i) ? false : true;
                    _cardColumns[i].AddCard(c);
                }
            }

            //then to the Start Pile...
            while (_deck.Count > 0)
            {
                _startPile.AddCard(_deck.Pop());
            }

        }

        private bool ModalCoverEnabled
        {
            get { return cvModalCover.Visibility == Visibility.Visible ? true : false; }
            set
            {
                if (value)
                {
                    cvModalCover.Width = LayoutRoot.ActualWidth;
                    cvModalCover.Height = LayoutRoot.ActualHeight;
                    cvModalCover.Visibility = Visibility.Visible;
                }
                else
                {
                    cvModalCover.Visibility = Visibility.Collapsed;
                }
            }
        }

        private void CenterInLayout(UserControl c)
        {
            double w = c.Width;
            double h = c.Height;
            if (w == double.NaN || h == double.NaN) return;
            w = w / 2;
            h = h / 2;
            Canvas.SetTop(c, LayoutRoot.ActualHeight / 2 - h);
            Canvas.SetLeft(c, LayoutRoot.ActualWidth / 2 - w);
        }

        private void UpdateBankRollDisplay()
        {
            Color lime = new Color()
            {
                A = 255,
                R = 0,
                G = 255,
                B = 0
            };
            tbBalance.Text = "$" + GameStatus.BankRoll.ToString();
            tbBalance.Foreground = (GameStatus.BankRoll >= 0) ? new SolidColorBrush(lime) : new SolidColorBrush(Colors.Yellow);
        }
        private void UpdateTimeDisplay()
        {
            tbTimer.Text = GameStatus.ElapsedSeconds.ToString();
        }

        internal void StopTimer()
        {
            _timer.Stop();
        }

        #endregion

        private void btnResetBalance_Click(object sender, RoutedEventArgs e)
        {
            MessageBoxResult r = MessageBox.Show("Resetting your bankroll will restart the current game.", "Are you sure?", MessageBoxButton.OKCancel);

            if (r == MessageBoxResult.OK)
            {
                GameStatus.BankRoll = 0;
                StartNewGame();
            }
        }

    }

    internal static class GameStatus
    {
        internal static int Passes { get; set; }
        internal static bool GameOver { get; set; }
        internal static GameSettings Preferences { get; set; }
        internal static TimeSpan ElapsedSeconds { get; set; }
        internal static int BankRoll { get; set; }
    }
}
